import { _decorator, Component, Node, instantiate, Prefab, tween, v2, Vec3, Button, NodePool, Pool, Label, Game, UITransform } from "cc";
import GameConfig from "../../constant/GameConfig";
import { EAreaID, ELogFromID, EPokerState } from "../../constant/GameEnum";
import { GameEvent } from "../../constant/GameEvent";
import ClosePokerGroupVo from "../../model/ClosePokerGroupVo";
import GameCtrl from "../../model/GameCtrl";
import LogPokerVo from "../../model/LogPokerVo";
import ModelGame from "../../model/ModelGame";
import PlayPokerGroupVo from "../../model/PlayPokerGroupVo";
import PokerVo from "../../model/PokerVo";
import ReceivePokerGroupVo from "../../model/ReceivePokerGroupVo";
import { ClickLock } from "../../utils/DecoratorUtils";
import PoolUtils from "../../utils/PoolUtils";
import UIUtils from "../../utils/UIUtils";
import UIPoker from "../poker/UIPoker";
const { ccclass, property } = _decorator;

@ccclass("GameView")
export class GameView extends Component {
  @property(Prefab)
  pokerPerfab: Prefab;
  @property(Prefab)
  gameOverPerfab: Prefab;
  @property(Node)
  rootArea: Node = null;
  @property(Node)
  initGroup: Node = null;
  @property(Node)
  sendArea: Node = null;
  @property(Node)
  playArea: Node = null;
  @property(Node)
  receiveArea: Node = null;
  @property(Node)
  closeSendArea: Node = null;
  @property(Node)
  openSendArea: Node = null;
  @property([Node])
  receiveAreaList: Node[] = [];
  @property(Node)
  playGroup: Node = null;
  @property(Button)
  btnReset: Button = null;
  @property(Button)
  btnResetClose: Button = null;
  @property(Button)
  btnAutoReceive: Button = null;
  @property(Button)
  btnRevoke: Button = null;
  @property(Label)
  labAuto: Label = null;
  @property(Button)
  btnTip: Button = null;
  @property(Label)
  labTip: Label = null;
  /**** */
  public registerEvent(): void {
    ModelGame.ins.on(GameEvent.INIT_POKER, this.onEventInitPoker.bind(this));
    ModelGame.ins.on(GameEvent.PLAY, this.onEventPlay.bind(this));
    ModelGame.ins.on(GameEvent.INIT_CORD, this.onEventInitCloseToPlay.bind(this));
    ModelGame.ins.on(GameEvent.CLIIC_UIPOKER, this.checkClickPoker.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_FROM_PLAY_TO_RECEIVE, this.onEventFromPlayToReceive.bind(this));
    ModelGame.ins.on(GameEvent.CHANGE_PLAY_POKER_STATE, this.onEventChangeTopPokerState.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_FROM_CLOSE_TO_OPEN, this.onEventFromCloseToOpen.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_OPEN_TO_RECEIVE, this.onEventFromOpenToReceive.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_FROM_OPEN_TO_CLOSE, this.onEventOpenToClose.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_FROM_OPEN_TO_PLAY, this.onEventFromOpenToPlay.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_FROM_PLAY_TO_PLAY, this.onEventFromPlayToPlay.bind(this));
    ModelGame.ins.on(GameEvent.MOVE_FROM_RECEIVE_TO_PLAY, this.onEventFromReceiveToPlay.bind(this));
    ModelGame.ins.on(GameEvent.DRAG_TO_RECEIVE, this.onEventDragToReceive.bind(this));
    ModelGame.ins.on(GameEvent.DRAG_ERROR, this.onEventDragError.bind(this));
    ModelGame.ins.on(GameEvent.DRAG_TO_PLAY, this.onEventDragToPlay.bind(this));
    ModelGame.ins.on(GameEvent.AUTO_RECEIVE, this.onEventAutoReceive.bind(this));
    ModelGame.ins.on(GameEvent.REVOKE_OPEN_TO_CLOSE, this.onEventRevokeOpenToClose.bind(this));
    ModelGame.ins.on(GameEvent.REVOKE_PLAY_TO_OPEN, this.onEventRevokePlayToOpen.bind(this));
    ModelGame.ins.on(GameEvent.REVOKE_RECEIVE_TO_OPEN, this.onEventRevokeReceiveToOpen.bind(this));
    ModelGame.ins.on(GameEvent.AUTO_TO_PLAY, this.onEventAutoToPlay.bind(this));
    this.btnReset.node.on("click", this.onResetClick.bind(this));
    this.btnResetClose.node.on("click", this.onbtnResetClose.bind(this));
    this.btnAutoReceive.node.on("click", this.onAutoReceive.bind(this));
    this.btnRevoke.node.on("click", this.onRevoke.bind(this));
    this.btnTip.node.on("click", this.onAutoPlay.bind(this));
  }

  public removeEvent(): void {
    ModelGame.ins.remove(GameEvent.INIT_POKER);
    ModelGame.ins.remove(GameEvent.PLAY);
    ModelGame.ins.remove(GameEvent.INIT_CORD);
    ModelGame.ins.remove(GameEvent.CLIIC_UIPOKER);
    ModelGame.ins.remove(GameEvent.MOVE_FROM_PLAY_TO_RECEIVE);
    ModelGame.ins.remove(GameEvent.CHANGE_PLAY_POKER_STATE);
    ModelGame.ins.remove(GameEvent.MOVE_FROM_CLOSE_TO_OPEN);
    ModelGame.ins.remove(GameEvent.MOVE_OPEN_TO_RECEIVE);
    ModelGame.ins.remove(GameEvent.MOVE_FROM_OPEN_TO_CLOSE);
    ModelGame.ins.remove(GameEvent.MOVE_FROM_OPEN_TO_PLAY);
    ModelGame.ins.remove(GameEvent.MOVE_FROM_PLAY_TO_PLAY);
    ModelGame.ins.remove(GameEvent.MOVE_FROM_RECEIVE_TO_PLAY);
    ModelGame.ins.remove(GameEvent.DRAG_TO_RECEIVE);
    ModelGame.ins.remove(GameEvent.DRAG_TO_PLAY);
    ModelGame.ins.remove(GameEvent.DRAG_ERROR);
    ModelGame.ins.remove(GameEvent.AUTO_RECEIVE);
    ModelGame.ins.remove(GameEvent.REVOKE_OPEN_TO_CLOSE);
    ModelGame.ins.remove(GameEvent.REVOKE_PLAY_TO_OPEN);
    ModelGame.ins.remove(GameEvent.REVOKE_RECEIVE_TO_OPEN);
    ModelGame.ins.remove(GameEvent.AUTO_TO_PLAY);
    this.btnReset.node.off("click", this.onResetClick.bind(this));
    this.btnResetClose.node.off("click", this.onbtnResetClose.bind(this));
    this.btnAutoReceive.node.off("click", this.onAutoReceive.bind(this));
    this.btnAutoReceive.node.off("click", this.onRevoke.bind(this));
    this.btnTip.node.off("click", this.onAutoPlay.bind(this));
  }

  /*** 生命周期函数 */
  onLoad(): void {
    this.registerEvent();
  }
  start() {}

  onDestroy(): void {
    this.removeEvent();
  }

  /**
   * 实例化扑克
   * 放到init组里
   */
  private initPokers(pokers: PokerVo[]): void {
    pokers.forEach((poker, index) => {
      let uiPoler: UIPoker = this.createUIPoker(poker);
      uiPoler.node.setPosition(0, 0);
      this.initGroup.addChild(uiPoler.node);
    });
  }

  /**
   * 创建扑克实例
   * 先从池子里要
   */
  private createUIPoker(poker: PokerVo): UIPoker {
    let pokerNode: Node = PoolUtils.ins.uiPoker.get();
    if (pokerNode == null) {
      pokerNode = instantiate(this.pokerPerfab);
    }
    let uiPoker: UIPoker = pokerNode.getComponent(UIPoker);
    uiPoker.init(poker, this);
    return uiPoker;
  }

  /**
   * 开始游戏
   * 从init组添加到close组
   * 设置zindex
   */
  private onPlay(): void {
    this.btnAutoReceive.node.active = false;
    this.labAuto.string = "自动收牌";
    this.labTip.string = "AI玩牌";
    for (let i = this.initGroup.children.length - 1; i >= 0; i--) {
      let child = this.initGroup.children[i];
      this.initGroup.removeChild(child);
      this.closeSendArea.addChild(child);
    }
    ModelGame.ins.closePokerArea.pokers.forEach((item) => {
      item.getView.node.setSiblingIndex(item.indexInGroup);
    });
  }

  /**
   *初始牌型
   */
  private onInteCard(poker: PokerVo): void {
    let playGroupVo: PlayPokerGroupVo = poker.parent as PlayPokerGroupVo;
    let node = poker.getView.node;
    let group: Node = this.playGroup;
    UIUtils.moveNodeByOtherNode(node, group);
    let index = group.children.length;
    let delay: number = index * 0.05;
    let px: number = playGroupVo.groupIndex * GameConfig.PLAY_POKER_X_SPACING;
    let tw = tween(node)
      .delay(delay)
      .to(0.3, { position: new Vec3(px, -GameConfig.PLAY_POKER_Y_SPACING * poker.indexInGroup, 1) })
      .call(() => {
        node.setSiblingIndex(index);
      });
    if (poker.state == EPokerState.OPEN) {
      tw = tw
        .to(0.15, { scale: new Vec3(0, 1, 1) })
        .call(() => {
          poker.getView.refresh();
        })
        .to(0.15, { scale: new Vec3(1, 1, 1) });
    }
    tw.start();
  }

  /**
   * 点击逻辑判断
   **/
  private checkClickPoker(pokerVo: PokerVo): void {
    if (this.isPlayArea(pokerVo)) {
      // 在play区域的牌处理
      if (this.isOpenByState(pokerVo)) {
        if (pokerVo.parent.topPoker === pokerVo) {
          ModelGame.ins.moveFromPlay(pokerVo);
        } else {
          ModelGame.ins.moveFromPlayToPlayForGroup(pokerVo);
        }
      }
    } else if (this.isCloseArea(pokerVo)) {
      // 在close区域牌处理
      if (pokerVo.parent.topPoker === pokerVo) {
        ModelGame.ins.moveFromClose(pokerVo);
      }
    } else if (this.isOpenArea(pokerVo)) {
      // 在open区域牌处理
      if (pokerVo.parent.topPoker === pokerVo) {
        ModelGame.ins.moveFromOpen(pokerVo);
      }
    } else if (this.isReceiveArea(pokerVo)) {
      // 在receive区域牌处理
      ModelGame.ins.moveFromReceive(pokerVo);
    }
  }

  /**
   * 拖拽逻辑判断
   * @param poker
   * @returns
   */
  private checkDragPos(poker: PokerVo): void {
    let receiveIndex: number = this.getReceiveIndexByDragPos(poker);
    if (receiveIndex !== -1) {
      ModelGame.ins.dragToReveive(poker, receiveIndex);
      return;
    }
    let playGroupIndex: number = this.getPlayIndexByDragPos(poker);
    if (playGroupIndex !== -1) {
      ModelGame.ins.dragToPlay(poker, playGroupIndex);
      return;
    }
    this.onEventDragError(poker);
  }

  /********* Evevt **********/

  //初始
  private onEventInitPoker(pokers: PokerVo[]): void {
    this.initPokers(pokers);
  }
  //开始
  private onEventPlay(): void {
    this.onPlay();
  }
  //初始牌型
  private onEventInitCloseToPlay(poker: PokerVo): void {
    this.onInteCard(poker);
  }

  // play to receive
  private onEventFromPlayToReceive(poker: PokerVo): void {
    this.moveToReceive(poker);
  }

  // play to play
  private onEventFromPlayToPlay(poker: PokerVo): void {
    this.moveToPlay(poker);
  }

  //poker_state-> close to open
  private onEventChangeTopPokerState(poker: PokerVo): void {
    this.changeTopPokerState(poker);
  }

  //close to open
  private onEventFromCloseToOpen(poker: PokerVo): void {
    this.moveToOpen(poker);
  }

  // open to receive
  private onEventFromOpenToReceive(poker: PokerVo): void {
    this.moveToReceive(poker);
    this.moveChangeOpen(false);
  }

  // open to play
  private onEventFromOpenToPlay(poker: PokerVo): void {
    this.moveToPlay(poker);
    this.moveChangeOpen(false);
  }

  // open to close
  private onEventOpenToClose(): void {
    this.moveToClose();
  }

  // receive to play
  private onEventFromReceiveToPlay(poker: PokerVo): void {
    this.moveToPlay(poker);
  }

  // drag to receive
  private onEventDragToReceive(data: [PokerVo, boolean]): void {
    this.moveToReceive(data[0]);
    if (data[1]) {
      this.moveChangeOpen(false);
    }
  }

  // drag to play
  private onEventDragToPlay(data: [PokerVo, boolean]): void {
    this.moveToPlay(data[0]);
    if (data[1]) {
      this.moveChangeOpen(false);
    }
  }

  // drag err
  private onEventDragError(poker: PokerVo): void {
    if (poker.parent.topPoker == poker) {
      if (this.isOpenArea(poker)) {
        this.moveChangeOpen(false);
      } else if (this.isReceiveArea(poker)) {
        this.moveToReceive(poker);
      } else {
        this.moveToPlay(poker);
      }
    } else {
      let pg = poker.parent as PlayPokerGroupVo;
      let pokers: PokerVo[] = pg.getConnectPoker(poker);
      for (let index = 0; index < pokers.length; index++) {
        let poker: PokerVo = pokers[index];
        this.moveToPlay(poker);
      }
    }
  }

  //自动收牌
  private onEventAutoReceive(poker: PokerVo): void {
    this.moveToReceive(poker);
    if (GameCtrl.ins.isAutoReceiveIng) {
      this.scheduleOnce(() => {
        ModelGame.ins.autoReceive();
      }, 0.2);
    }
  }

  // revoke open to close
  private onEventRevokeOpenToClose(poker: PokerVo): void {
    this.revokeOpenToClose(poker);
  }

  // revoke play to open
  private onEventRevokePlayToOpen(poker: PokerVo): void {
    this.revokePlayToOpen(poker);
  }

  // revoke play to receive
  private onEventRevokeReceiveToOpen(poker: PokerVo): void {
    this.revokeReceiveToOpen(poker);
  }

  //自动玩牌
  private onEventAutoToPlay(): void {
    if (!GameCtrl.ins.isAIAutoPlayIng) {
      return;
    }
    this.scheduleOnce(() => {
      ModelGame.ins.autoPlay();
    }, 0.4);
  }

  /************ Handler ************/

  //重新开局
  @ClickLock(5)
  private onResetClick(): void {
    if (GameCtrl.ins.isAIAutoPlayIng || GameCtrl.ins.isAutoReceiveIng) {
      return;
    }
    ModelGame.ins.pokers.forEach((item) => {
      let node = item.getView.node;
      PoolUtils.ins.uiPoker.put(node);
    });
    GameCtrl.ins.newGame();
  }

  //点击poker
  public onClickUIPoker(poker: PokerVo): void {
    this.checkClickPoker(poker);
  }

  //拖拽
  public onDragUIPoker(poker: PokerVo): void {
    this.checkDragPos(poker);
  }

  @ClickLock(1)
  private onbtnResetClose(): void {
    ModelGame.ins.moveOpenPokersToClose();
  }

  //自动收牌
  private onAutoReceive(): void {
    if (GameCtrl.ins.isAIAutoPlayIng) {
      return;
    }
    if (!GameCtrl.ins.isAutoReceiveIng) {
      this.labAuto.string = "停止收牌";
      GameCtrl.ins.isAutoReceiveIng = true;
      ModelGame.ins.autoReceive();
    } else {
      this.labAuto.string = "自动收牌";
      GameCtrl.ins.isAutoReceiveIng = false;
    }
  }

  //撤销
  @ClickLock(0.5)
  private onRevoke(): void {
    if (!GameCtrl.ins.haveLogPoker || GameCtrl.ins.isAIAutoPlayIng || GameCtrl.ins.isAutoReceiveIng) {
      return;
    }
    let logPoker: LogPokerVo = GameCtrl.ins.popLogPoker();
    if (logPoker.from == ELogFromID.CLOSE_TO_OPEN) {
      ModelGame.ins.revokeOpenToClose(logPoker.pokers[0]);
    } else if (logPoker.from == ELogFromID.OPEN_TO_PLAY) {
      ModelGame.ins.revokePlayToOpen(logPoker);
    } else if (logPoker.from == ELogFromID.OPEN_TO_RECEIVE) {
      ModelGame.ins.revokeReceiveToOpen(logPoker);
    } else if (logPoker.from == ELogFromID.PLAY_TO_PLAY) {
      ModelGame.ins.revokePlayToPlay(logPoker);
    } else if (logPoker.from == ELogFromID.PLAY_TO_RECEIVE) {
      ModelGame.ins.revokeReceiveToPlay(logPoker);
    } else if (logPoker.from == ELogFromID.RECEIVE_TO_PLAY) {
      ModelGame.ins.revokePlayToReceive(logPoker);
    } else if (logPoker.from == ELogFromID.RECEIVE_TO_OPEM) {
      ModelGame.ins.revokePlayToReceive(logPoker);
    } else if (logPoker.from == ELogFromID.OPEN_POKERS_TO_CLOSE) {
      ModelGame.ins.revokeCloseToReceive();
    }
  }

  //提示
  private onAutoPlay(): void {
    if (GameCtrl.ins.isAutoReceiveIng) {
      return;
    }
    if (!GameCtrl.ins.isAIAutoPlayIng) {
      GameCtrl.ins.isAIAutoPlayIng = true;
      this.labTip.string = "取消AI";
      ModelGame.ins.autoPlay();
    } else {
      GameCtrl.ins.isAIAutoPlayIng = false;
      this.labTip.string = "AI玩牌";
    }
  }

  private onGamgOver(): void {
    if (ModelGame.ins.checkIsGameOver() && !GameCtrl.ins.isGameOver) {
      GameCtrl.ins.isGameOver = true;
      let node = instantiate(this.gameOverPerfab);
      this.node.addChild(node);
    }
  }
  /************* API *****************/

  /** 移动到receive */
  private moveToReceive(poker: PokerVo): void {
    this.onGamgOver();
    this.changeAreaOrder(poker);
    let node = poker.getView.node;
    let group: Node = this.receiveAreaList[(poker.parent as PlayPokerGroupVo).groupIndex];
    UIUtils.moveNodeByOtherNode(node, group);
    let tw = tween(node)
      .to(0.2, { position: this.getPositionByArea(poker) })
      .call(() => {
        node.setSiblingIndex(poker.indexInGroup);
      })
      .start();
  }

  /** 移动到play */
  private moveToPlay(poker: PokerVo): void {
    this.changeAreaOrder(poker);
    let node = poker.getView.node;
    UIUtils.moveNodeByOtherNode(node, this.playGroup);
    let tw = tween(node)
      .to(0.2, { position: this.getPositionByArea(poker) })
      .call(() => {})
      .start();

    if (ModelGame.ins.checkAutoReceive()) {
      this.btnAutoReceive.node.active = true;
    }
  }

  /**
   * 翻转最顶部的牌
   */
  private changeTopPokerState(poker: PokerVo): void {
    let node = poker.getView.node;
    let tw = tween(node)
      .to(0.3, { scale: new Vec3(0, 1, 1) })
      .call(() => {
        poker.getView.refresh();
      })
      .to(0.3, { scale: new Vec3(1, 1, 1) })
      .start();
  }

  /**移动到open */
  private moveToOpen(poker: PokerVo): void {
    let node = poker.getView.node;
    UIUtils.moveNodeByOtherNode(node, this.openSendArea);
    node.setSiblingIndex(poker.parent.getIndexByGroup(poker));
    let PX_TIME: number = 0.2;
    let NX: number = node.getPosition().x;
    let tw = tween(node)
      .to(PX_TIME, {
        scale: new Vec3(0, 1, 1),
        position: new Vec3(NX / 2, 0, 0),
      })
      .call(() => poker.getView.refresh())
      .to(PX_TIME, { scale: new Vec3(1, 1, 1), position: new Vec3(0, 0, 1) })
      .start();
    this.moveChangeOpen(true);
  }

  //移动到close
  private moveToClose(): void {
    let CPG: ClosePokerGroupVo = ModelGame.ins.closePokerArea;
    this.closeSendArea.setSiblingIndex(this.sendArea.children.length);
    for (let i = 0; i < CPG.pokers.length; i++) {
      let poker: PokerVo = CPG.pokers[i];

      let node = poker.getView.node;
      UIUtils.moveNodeByOtherNode(node, this.closeSendArea);
      node.setSiblingIndex(i);
      let dx = node.getPosition().x - 0;
      let tw = tween(node)
        .delay(i * 0.001)
        .to(0.05, { scale: new Vec3(0, 1, 1), position: new Vec3(dx / 2, 0, 1) })
        .call(() => {
          poker.getView.refresh();
        })
        .to(0.05, { scale: new Vec3(1, 1, 1), position: new Vec3(0, 0, 1) })

        .start();
    }
  }

  /**
   * 改变open排列
   *  close to open
   *  open to other
   */
  private moveChangeOpen(fromClose: boolean = false) {
    let num: number = fromClose ? 1 : 0;
    let PX_TIME: number = 0.2;
    for (let i = 0; i <= 1; i++) {
      let p: PokerVo = ModelGame.ins.openPokerArea.getPokerByIndex(-(1 + num) - i);
      if (p) {
        tween(p.getView.node)
          .to(PX_TIME * 2, { position: new Vec3(-20 * (i + num), 0, 1) })
          .start();
      }
    }
  }

  /**
   * 撤销 to open
   * @param poker
   */
  private revokeToOpen(poker: PokerVo): void {
    this.changeAreaOrder(poker);
    let node = poker.getView.node;
    UIUtils.moveNodeByOtherNode(node, this.openSendArea);
    node.setSiblingIndex(poker.parent.Length);
    let tw = tween(node)
      .to(0.2, { scale: new Vec3(1, 1, 1), position: new Vec3(0, 0, 1) })
      .start();
    this.moveChangeOpen(true);
  }

  /**
   * 撤销 open to close
   * @param poker
   */
  private revokeOpenToClose(poker: PokerVo): void {
    this.changeAreaOrder(poker);
    let node = poker.getView.node;
    UIUtils.moveNodeByOtherNode(node, this.closeSendArea);
    node.setSiblingIndex(poker.parent.Length);
    let dx = node.getPosition().x - 0;
    poker.getView.refresh();
    let tw = tween(node)
      .to(0.1, { position: new Vec3(dx / 2, 0, 1) })
      .call(() => {
        this.moveChangeOpen(false);
      })
      .to(0.1, { position: new Vec3(0, 0, 1) })
      .start();
  }

  /**
   * 撤销 play to open
   * @param poker
   */
  private revokePlayToOpen(poker: PokerVo): void {
    this.revokeToOpen(poker);
  }

  /**
   * 撤销 receive to open
   * @param poker
   */
  private revokeReceiveToOpen(poker: PokerVo): void {
    this.revokeToOpen(poker);
  }

  /**
   * 拖拽时改变区域层级
   */
  public changeAreaOrder(poker: PokerVo): void {
    let topAreaOrder: number = this.rootArea.children.length;
    if (this.isPlayArea(poker)) {
      this.playArea.setSiblingIndex(topAreaOrder);
    } else if (this.isOpenArea(poker)) {
      this.sendArea.setSiblingIndex(topAreaOrder);
      this.openSendArea.setSiblingIndex(this.sendArea.children.length);
    } else if (this.isReceiveArea(poker)) {
      this.receiveArea.setSiblingIndex(topAreaOrder);
      this.changeReceiveOrder(poker);
    } else if (this.isCloseArea(poker)) {
      this.sendArea.setSiblingIndex(topAreaOrder);
      this.closeSendArea.setSiblingIndex(this.sendArea.children.length);
    }
  }

  /**
   * 改变receiveGroup的层级
   */
  private changeReceiveOrder(poker: PokerVo): void {
    let topOrder: number = (poker.parent as ReceivePokerGroupVo).groupIndex;
    let receiveNode: Node = this.receiveAreaList[topOrder];
    receiveNode.setSiblingIndex(this.receiveArea.children.length);
  }

  /**
   * 拖拽时改变poker在本区域的层级
   */
  public changePokerInGroupOrder(poker: PokerVo): number {
    if (this.isPlayArea(poker)) {
      return ModelGame.ins.getPokerNumInPlayGroups();
    } else if (this.isOpenArea(poker)) {
      return ModelGame.ins.getPokerNumInOpenAndClose();
    } else if (this.isReceiveArea(poker)) {
      return ModelGame.ins.getPokerNumInReceiveGroups();
    }
  }
  /**
   * 计算出三个可移动区域位置
   */
  private getPositionByArea(poker: PokerVo): Vec3 {
    let areaID: EAreaID = poker.parent.areaID;
    switch (areaID) {
      case EAreaID.RECEIVE:
        return new Vec3(0, 0, 0);
      case EAreaID.PLAY:
        let parent = poker.parent as PlayPokerGroupVo;
        return new Vec3(parent.groupIndex * GameConfig.PLAY_POKER_X_SPACING, -poker.indexInGroup * GameConfig.PLAY_POKER_Y_SPACING, 0);
      case EAreaID.OPEN:
        let pokerIndex = poker.parent.getIndexByGroup(poker);
        let pokerL = poker.parent.Length;
        return new Vec3(-20 * (pokerL - pokerIndex), 0, 0);
      default:
        return new Vec3(0, 0, 0);
    }
  }

  /**
   *  拖拽到receive的位置
   * @param poker
   * @returns
   */
  private getReceiveIndexByDragPos(poker: PokerVo): number {
    if (this.isReceiveArea(poker)) {
      return -1;
    }
    let node: Node = poker.getView.node;
    for (let receiveIndex = 0; receiveIndex < this.receiveAreaList.length; receiveIndex++) {
      let receiveNode: Node = this.receiveAreaList[receiveIndex];
      let pos: Vec3 = UIUtils.convetOtherNodeSpaceAR(node, receiveNode);
      if (Math.abs(pos.x) < 50 && Math.abs(pos.y) < 70) {
        return receiveIndex;
      }
    }
    return -1;
  }

  /**
   *
   * @param poker 拖拽到play的位置
   * @returns
   */
  private getPlayIndexByDragPos(poker: PokerVo): number {
    let node: Node = poker.getView.node;
    for (let playIndex = 0; playIndex < ModelGame.ins.playPokerGroup.length; playIndex++) {
      let playGroup: PlayPokerGroupVo = ModelGame.ins.playPokerGroup[playIndex];
      let pokerIndex: number = playGroup.havePoker ? playGroup.Length - 1 : 0;
      let pos: Vec3 = UIUtils.moveNodeByPostion(node, this.playGroup);
      let pos1 = UIUtils.getPokerTargetWorldPostionOfPlay(playIndex, pokerIndex);
      if (Math.abs(pos.x - pos1.x) < 40 && Math.abs(pos.y - pos1.y) < 50) {
        return playIndex;
      }
    }
    return -1;
  }

  /**处于play区域 */
  public isPlayArea(poker: PokerVo): boolean {
    return poker.parent.areaID == EAreaID.PLAY;
  }
  /**处于receive区域 */
  public isReceiveArea(poker: PokerVo): boolean {
    return poker.parent.areaID == EAreaID.RECEIVE;
  }
  /**处于close区域 */
  public isCloseArea(poker: PokerVo): boolean {
    return poker.parent.areaID == EAreaID.CLOSE;
  }
  /**处于open区域 */
  public isOpenArea(poker: PokerVo): boolean {
    return poker.parent.areaID == EAreaID.OPEN;
  }
  /**此牌是否翻开 */
  public isOpenByState(poker: PokerVo): boolean {
    return poker.state == EPokerState.OPEN;
  }
}
